home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
v7n15.arc
/
FILECOPY.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-08-09
|
10KB
|
187 lines
;FileCopy.ASM - copies a source file to a target file.
;Written by J. R. Conrad, Baltimore, MD
;----------------------------------------------------------------------
; 1) Assemble FileCopy.Asm to FileCopy.Obj
; 2) Use BuildLib to add FileCopy.Obj to UserLib.Exe
;----------------------------------------------------------------------
;Basic Syntax: Call FileCopy(InFile$, OutFile$, Buffer$, ErrCode%).
; Where: InFile$ = source path and filename,
; OutFile$ = target path and filename,
; Buffer$ = blank string (64 < Len < 32768)
; ErrCode% = 1 if source path not found
; 2 if source file not found (3 not used)
; 4 if source file is a directory
; 5 if source file not accessible
; 6 if target path not found
; 7 if target filename is invalid
; 8 if target directory is full
; 9 if target file is a directory
; 10 if target file is read-only
; 11 if target file not accessible
; 12 if target disk is full
; 13 if length of Buffer$ < 65 bytes
;
; Notes: 1) Critical errors must be captured with On Error,
; 2) Always reenter with ErrCode% = -1 after critical errors.
;-----------------------------------------------------------------------
Code Segment Byte Public 'Code'
Assume CS:Code
Public FileCopy
FileCopy Proc Far
Begin: Jmp Start ;Local data follows:
Source_Handle DW 0
Target_Handle DW 0
Buffer_Size DW 0
Bytes_Read DW 0
File_Time DW ?
File_Date DW ?
Root_Test DB ':\',0
Start: Push BP ;Save BP.
Mov BP,SP ;Get stack pointer to parameters.
Mov AX,DS ;Insure ES = DS.
Mov ES,AX
Xor BX,BX ;Zero error code.
Cld ;Forward string primitives.
Mov SI,[BP+6] ;Recover from critical error?
Cmp Word Ptr [SI],-1 ;If ErrCode% = -1,
Jne Check_Buffer ; then close open files from
Jmp Close_Files ; previous call.
Check_Buffer: Mov SI,[BP+8] ;Make sure buffer is big enough:
Cmp Word Ptr [SI],64 ; is it longer than 64 char?
Ja Open_Source ;If so, then continue.
Mov BX,13 ;Else, set ErrCode% and return.
Jmp Close_Files
Open_Source: Mov AX,[SI] ;Save buffer size.
Mov Buffer_Size,AX
Mov DX,[SI+2] ;DX = offset of Buffer$
Mov SI,[BP+12] ;Point SI to InFile$.
Mov BX,1 ;Init error code.
Call Load_File ;Convert to ASCIIZ.
Mov AX,3D00h ;Request Open File (read-only).
Int 21h
Jnc Open_Target ;Did an error occur?
Call Find_Err ;If so, run the error analysis.
Je Source_Err ; If ZF, error was found.
Inc BX ; Else, access denied.
Source_Err: Jmp Close_Files
Open_Target: Mov Source_Handle,AX ;Save the source file handle.
Mov BX,AX ;Save file handle in BX
Mov AX,5700h ;Get time and date from source
Push DX ;Save buffer$ address in DX
Int 21h ;Get source file's date and time
Mov File_Time,CX ; save them
Mov File_Date,DX ; internally
Pop DX ;Retrieve DX
Mov SI,[BP+10] ;Point SI to OutFile$.
Mov BX,6 ;Init error code.
Call Load_File ;Convert to ASCIIZ.
Mov AH,3Ch ;Request Create/Clear File:
Mov CX,0 ; target is normal file,
Int 21h ; do it.
Jnc Prep_Copy ;Did an error occur?
Call Find_Err ;If so, run the error analysis:
Jc Target_Err ; If CF, directory is full.
Je Target_Err ; If ZF, error was found.
Inc BX
Test AX,1 ; Else, if NOT (attribute AND 1),
Jz Target_Err ; target is read-only.
Inc BX ; Else, access denied.
Target_Err: Jmp Close_Files
Prep_Copy: Mov Target_Handle,AX ;Save the target file handle.
Mov CX,Buffer_Size ;Put buffer size in CX.
Do_Copy: Mov AH,3Fh ;Request Read from File service:
Mov BX,Source_Handle ; retrieve source handle,
Int 21h ; do it.
Mov Bytes_Read,AX ;Store bytes actually read,
Mov CX,AX ; store in CX for write.
Mov AH,40h ;Request Write to File service:
Mov BX,Target_Handle ; retrieve handle,
Int 21h ; do it.
Mov BX,12 ;Test for full disk:
Cmp AX,CX ; if bytes written <> read,
Jne Close_Files ; then disk is full.
Mov CX,Buffer_Size ;Retrieve buffer size.
Cmp CX,Bytes_Read ;Test for EOF.
Je Do_Copy
Mov AX,5701h ;Set target file date and time
Mov BX,Target_Handle ;Specify target file handle
Mov CX,File_Time ;Use the source date and time
Mov DX,File_Date ; saved earlier
Int 21h
Xor BX,BX ;Successful copy, error code = 0!
Close_Files: Cmp Source_Handle,0 ;Is source open?
Je Basic_Return ; If no, then no files open.
Push BX ;Save BX for widow check.
Cmp Target_Handle,0 ;Is target open?
Je Source_Only ; If no, then only source open.
Mov AH,3Eh ;Request file closing service.
Mov BX,Target_Handle ;Close target file.
Int 21h
Mov Target_Handle,0
Source_Only: Mov AH,3Eh ;Request file closing service.
Mov BX,Source_Handle ;Close source file.
Int 21h
Mov Source_Handle,0
Widow_Check: Pop BX ;Check for disk full case.
Cmp BX,12 ;If disk full error, then delete
Jne Basic_Return ; partial target file.
Mov SI,[BP+10] ;Point SI to OutFile$.
Call Load_File ;Convert to ASCIIZ.
Mov AH,41h ;Request file deletion service.
Int 21h
Basic_Return: Mov DI,[BP+6] ;Set error flag.
Mov [DI],BX
Pop BP ;Restore BP.
Ret 8 ;Cleanup stack and return.
Load_File Proc Near ;Convert filename to ASCIIZ format:
Mov CX,[SI] ;Get length of string,
Cmp CX,64 ;Is the string too long?
Jbe Do_Load ;If not, continue w/ load.
Add SP,2 ;Else, fix the stack
Jmp Close_Files ; and jump to exit.
Do_Load: Mov SI,[SI+2] ;Point SI to filename.
Mov DI,DX ;Point DI to buffer.
Rep Movsb ;Transfer pathname
Mov Byte Ptr [DI],0 ; and make ASCIIZ.
Ret
Load_File Endp
Find_Err Proc Near ;Determine source of error.
Cmp AX,3 ;If AX = 3,
Je End_Find ; then invalid path.
Inc BX
Cmp AX,2 ;Else, if AX = 2,
Je End_Find ; then file not found.
Inc BX
Mov AX,4300h ;Else, retrieve file attribute.
Int 21h
Jc End_Find ;If carry, file does not exist.
Inc BX
Mov AX,CX ;Save attribute in AX.
Xor AX,0FFFFh ;Use inverted logic!
Test AX,10h ;Test for a subdirectory.
Je End_Find ;If ZF, then subdirectory.
Mov CX,3 ;Else, check for root directory:
Mov SI,Offset Root_Test ; point SI to root string,
Mov DI,DX ; point DI to 2nd character,
Inc DI
Repe Cmps CS:Byte Ptr [SI],[DI] ;compare strings,
Clc ; cancel side-effect on carry.
End_Find: Ret
Find_Err Endp
FileCopy Endp
Code Ends
End Begin